<!-- yangbuyi Copyright (c) https://yby6.com 2023. -->

<template>
  <u-transition mode="slide-down" :customStyle="containerStyle" :show="open">
    <view
      class="u-notify"
      :class="[`u-notify--${tmpConfig.type}`]"
      :style="[backgroundColor, $u.addStyle(customStyle)]"
    >
      <u-status-bar v-if="tmpConfig.safeAreaInsetTop"></u-status-bar>
      <view class="u-notify__warpper">
        <slot name="icon">
          <u-icon
            v-if="['success', 'warning', 'error'].includes(tmpConfig.type)"
            :name="tmpConfig.icon"
            :color="tmpConfig.color"
            :size="1.3 * tmpConfig.fontSize"
            :customStyle="{ marginRight: '4px' }"
          ></u-icon>
        </slot>
        <text
          class="u-notify__warpper__text"
          :style="{
            fontSize: $u.addUnit(tmpConfig.fontSize),
            color: tmpConfig.color,
          }"
          >{{ tmpConfig.message }}</text
        >
      </view>
    </view>
  </u-transition>
</template>

<script>
import props from "./props.js";
/**
 * notify 顶部提示
 * @description 该组件一般用于页面顶部向下滑出一个提示，尔后自动收起的场景
 * @tutorial
 * @property {String | Number}	top					到顶部的距离 ( 默认 0 )
 * @property {String}			type				主题，primary，success，warning，error ( 默认 'primary' )
 * @property {String}			color				字体颜色 ( 默认 '#ffffff' )
 * @property {String}			bgColor				背景颜色
 * @property {String}			message				展示的文字内容
 * @property {String | Number}	duration			展示时长，为0时不消失，单位ms ( 默认 3000 )
 * @property {String | Number}	fontSize			字体大小 ( 默认 15 )
 * @property {Boolean}			safeAreaInsetTop	是否留出顶部安全距离（状态栏高度） ( 默认 false )
 * @property {Object}			customStyle			组件的样式，对象形式
 * @event {Function}	open	开启组件时调用的函数
 * @event {Function}	close	关闭组件式调用的函数
 * @example <u-notify message="Hi uView"></u-notify>
 */
export default {
  name: "u-notify",
  mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  data() {
    return {
      // 是否展示组件
      open: false,
      timer: null,
      config: {
        // 到顶部的距离
        top: uni.$u.props.notify.top,
        // type主题，primary，success，warning，error
        type: uni.$u.props.notify.type,
        // 字体颜色
        color: uni.$u.props.notify.color,
        // 背景颜色
        bgColor: uni.$u.props.notify.bgColor,
        // 展示的文字内容
        message: uni.$u.props.notify.message,
        // 展示时长，为0时不消失，单位ms
        duration: uni.$u.props.notify.duration,
        // 字体大小
        fontSize: uni.$u.props.notify.fontSize,
        // 是否留出顶部安全距离（状态栏高度）
        safeAreaInsetTop: uni.$u.props.notify.safeAreaInsetTop,
      },
      // 合并后的配置，避免多次调用组件后，可能会复用之前使用的配置参数
      tmpConfig: {},
    };
  },
  computed: {
    containerStyle() {
      let top = 0;
      if (this.tmpConfig.top === 0) {
        // #ifdef H5
        // H5端，导航栏为普通元素，需要将组件移动到导航栏的下边沿
        // H5的导航栏高度为44px
        top = 44;
        // #endif
      }
      const style = {
        top: uni.$u.addUnit(
          this.tmpConfig.top === 0 ? top : this.tmpConfig.top
        ),
        // 因为组件底层为u-transition组件，必须将其设置为fixed定位
        // 让其出现在导航栏底部
        position: "fixed",
        left: 0,
        right: 0,
        zIndex: 10076,
      };
      return style;
    },
    // 组件背景颜色
    backgroundColor() {
      const style = {};
      if (this.tmpConfig.bgColor) {
        style.backgroundColor = this.tmpConfig.bgColor;
      }
      return style;
    },
    // 默认主题下的图标
    icon() {
      let icon;
      if (this.tmpConfig.type === "success") {
        icon = "checkmark-circle";
      } else if (this.tmpConfig.type === "error") {
        icon = "close-circle";
      } else if (this.tmpConfig.type === "warning") {
        icon = "error-circle";
      }
      return icon;
    },
  },
  created() {
    // 通过主题的形式调用toast，批量生成方法函数
    ["primary", "success", "error", "warning"].map((item) => {
      this[item] = (message) =>
        this.show({
          type: item,
          message,
        });
    });
  },
  methods: {
    show(options) {
      // 不将结果合并到this.config变量，避免多次调用u-toast，前后的配置造成混乱
      this.tmpConfig = uni.$u.deepMerge(this.config, options);
      // 任何定时器初始化之前，都要执行清除操作，否则可能会造成混乱
      this.clearTimer();
      this.open = true;
      if (this.tmpConfig.duration > 0) {
        this.timer = setTimeout(() => {
          this.open = false;
          // 倒计时结束，清除定时器，隐藏toast组件
          this.clearTimer();
          // 判断是否存在callback方法，如果存在就执行
          typeof this.tmpConfig.complete === "function" &&
            this.tmpConfig.complete();
        }, this.tmpConfig.duration);
      }
    },
    // 关闭notify
    close() {
      this.clearTimer();
    },
    clearTimer() {
      this.open = false;
      // 清除定时器
      clearTimeout(this.timer);
      this.timer = null;
    },
  },
  beforeDestroy() {
    this.clearTimer();
  },
};
</script>

<style lang="scss" scoped>
@import "../../libs/css/components.scss";

$u-notify-padding: 8px 10px !default;
$u-notify-text-font-size: 15px !default;
$u-notify-primary-bgColor: $u-primary !default;
$u-notify-success-bgColor: $u-success !default;
$u-notify-error-bgColor: $u-error !default;
$u-notify-warning-bgColor: $u-warning !default;

.u-notify {
  padding: $u-notify-padding;

  &__warpper {
    @include flex;
    align-items: center;
    text-align: center;
    justify-content: center;

    &__text {
      font-size: $u-notify-text-font-size;
      text-align: center;
    }
  }

  &--primary {
    background-color: $u-notify-primary-bgColor;
  }

  &--success {
    background-color: $u-notify-success-bgColor;
  }

  &--error {
    background-color: $u-notify-error-bgColor;
  }

  &--warning {
    background-color: $u-notify-warning-bgColor;
  }
}
</style>
